!! Copyright (C) 2009,2010,2011,2012  Marco Restelli
!!
!! This file is part of:
!!   FEMilaro -- Finite Element Method toolkit
!!
!! FEMilaro is free software; you can redistribute it and/or modify it
!! under the terms of the GNU General Public License as published by
!! the Free Software Foundation; either version 3 of the License, or
!! (at your option) any later version.
!!
!! FEMilaro is distributed in the hope that it will be useful, but
!! WITHOUT ANY WARRANTY; without even the implied warranty of
!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
!! General Public License for more details.
!!
!! You should have received a copy of the GNU General Public License
!! along with FEMilaro; If not, see <http://www.gnu.org/licenses/>.
!!
!! author: Marco Restelli                   <marco.restelli@gmail.com>

module mod_octave_io_sympoly
!General comments: octave io for symbolic polynomials. A polynomial is
!written as a two dimensional array, so that each row has the
!following meaning:
!
!  [   coefficients  ]
!  [ exponents of x1 ]
!  [ exponents of x2 ]
!  [       ...       ]
!-----------------------------------------------------------------------

!-----------------------------------------------------------------------

 use mod_messages, only: &
   mod_messages_initialized, &
   error,   &
   warning, &
   info

 use mod_kinds, only: &
   mod_kinds_initialized, &
   wp

 use mod_octave_io, only: &
   mod_octave_io_initialized, &
   write_octave, &
   real_format

 use mod_sympoly, only: &
   mod_sympoly_initialized, &
   t_symmon,       &
   t_sympol,       &
   red_sympoly,    &
   test,           &
   wrong_input,    &
   wrong_previous, &
   wrong_monomials 

!-----------------------------------------------------------------------
 
 implicit none

!-----------------------------------------------------------------------

! Module interface

 public :: &
   mod_octave_io_sympoly_constructor, &
   mod_octave_io_sympoly_destructor,  &
   mod_octave_io_sympoly_initialized, &
   write_octave

 private

!-----------------------------------------------------------------------

! Module types and parameters

! Module variables

 ! public members
 logical, protected ::               &
   mod_octave_io_sympoly_initialized = .false.

 character(len=*), parameter :: &
   this_mod_name = 'mod_octave_io_sympoly'

 interface write_octave
   module procedure write_sympol
 end interface

!-----------------------------------------------------------------------

contains

!-----------------------------------------------------------------------

 subroutine mod_octave_io_sympoly_constructor()
  character(len=*), parameter :: &
    this_sub_name = 'constructor'

   !Consistency checks ---------------------------
   if( (mod_messages_initialized.eqv..false.) .or. &
       (mod_kinds_initialized.eqv..false.)    .or. &
       (mod_octave_io_initialized.eqv..false.).or. &
       (mod_sympoly_initialized.eqv..false.) ) then
     call error(this_sub_name,this_mod_name, &
                'Not all the required modules are initialized.')
   endif
   if(mod_octave_io_sympoly_initialized.eqv..true.) then
     call warning(this_sub_name,this_mod_name, &
                  'Module is already initialized.')
   endif
   !----------------------------------------------

   mod_octave_io_sympoly_initialized = .true.
 end subroutine mod_octave_io_sympoly_constructor

!-----------------------------------------------------------------------
 
 subroutine mod_octave_io_sympoly_destructor()
  character(len=*), parameter :: &
    this_sub_name = 'destructor'
   
   !Consistency checks ---------------------------
   if(mod_octave_io_sympoly_initialized.eqv..false.) then
     call error(this_sub_name,this_mod_name, &
                'This module is not initialized.')
   endif
   !----------------------------------------------

   mod_octave_io_sympoly_initialized = .false.
 end subroutine mod_octave_io_sympoly_destructor

!-----------------------------------------------------------------------
 
 subroutine write_sympol(p,var_name,fu)
  integer, intent(in) :: fu
  type(t_sympol), intent(in) :: p
  character(len=*), intent(in) :: var_name
 
  integer :: i, ix
  real(wp), allocatable :: pmat(:,:)
  type(t_sympol) :: q
  character(len=*), parameter :: &
    this_sub_name = 'write_sympol'
 
   select case(test(p))
    case(0)

     q = red_sympoly(p)

     allocate(pmat(maxval(q%mons(:)%nsv)+1,q%nmon))
     pmat = 0.0_wp
     do i=1,q%nmon
       pmat(1,i) = q%mons(i)%coeff
       do ix=1,q%mons(i)%nsv
         pmat(1+ix,i) = real(q%mons(i)%degs(ix),wp)
       enddo
     enddo
     call write_octave(pmat,var_name,fu)
     deallocate(pmat)
     
    case(wrong_input)
     call write_octave('wrong_input',var_name,fu)
    case(wrong_previous)
     call write_octave('wrong_previous',var_name,fu)
    case(wrong_monomials)
     call write_octave('wrong_monomials',var_name,fu)
   end select

 end subroutine write_sympol
 
!-----------------------------------------------------------------------

end module mod_octave_io_sympoly

